package com.github.glomadrian.materialanimatedswitch.painter;

import com.github.glomadrian.materialanimatedswitch.MaterialAnimatedSwitchState;
import com.github.glomadrian.materialanimatedswitch.observer.BallFinishObservable;
import com.github.glomadrian.materialanimatedswitch.observer.BallMoveObservable;
import com.github.glomadrian.materialanimatedswitch.utils.AnimatorValueUtils;
import com.github.glomadrian.materialanimatedswitch.utils.Utils;
import ohos.agp.animation.AnimatorValue;
import ohos.app.Context;
import ohos.media.image.PixelMap;

import java.util.Observable;
import java.util.Observer;

public class IconPressPainter extends IconPainter {
    private AnimatorValue enterAnimator;
    private AnimatorValue exitAnimator;
    private BallFinishObservable ballFinishObservable;
    private int enterAnimationStartValue;
    private int exitAnimationExitValue;
    private int middle;
    private int iconMargin;
    private int ballRadius;
    private BallMoveObservable ballMoveObservable;

    public IconPressPainter(Context context,
                            PixelMap bitmap,
                            BallFinishObservable ballFinishObservable,
                            BallMoveObservable ballMoveObservable,
                            int margin) {
        super(context, bitmap, margin);
        initValueAnimator();
        this.ballFinishObservable = ballFinishObservable;
        this.ballMoveObservable = ballMoveObservable;
        initObserver();
    }

    private void initValueAnimator() {
        int movementAnimationDuration = 400;
        int exitAnimationDuration = 200;

        enterAnimator = new AnimatorValue();
        enterAnimator.setDuration(movementAnimationDuration);
        enterAnimator.setValueUpdateListener(new EnterValueAnimatorListener());

        exitAnimator = new AnimatorValue();
        exitAnimator.setDuration(exitAnimationDuration);
        exitAnimator.setValueUpdateListener(new ExitValueAnimatorListener());
    }

    @Override
    public void onSizeChanged(int height, int width) {
        super.onSizeChanged(height, width);
        initValues();
        initAnimationValues();
    }

    private void initValues() {
        middle = height / 2;
        iconMargin = imageWidth / 2;
        ballRadius = Utils.vp2px(context, 11);
        iconXPosition = (width - ballRadius) + iconMargin;
    }

    private void initAnimationValues() {
        enterAnimationStartValue =
                -Utils.vp2px(context, 25);
        exitAnimationExitValue =
                Utils.vp2px(context, 25);
    }

    @Override
    public int getColor() {
        return 0;
    }

    @Override
    public void setColor(int color) {
    }

    private void initObserver() {
        ballFinishObservable.addObserver(new BallFinishListener());
        ballMoveObservable.addObserver(new BallMoveListener());
    }

    @Override
    public void setState(MaterialAnimatedSwitchState state) {
        switch (state) {
            case PRESS:
                isVisible = true;
                enterAnimator.start();
                break;
            case RELEASE:
                exitAnimator.start();
                break;
            default:
                break;
        }
    }

    private class BallFinishListener implements Observer {
        @Override
        public void update(Observable observable, Object data) {
            BallFinishObservable.BallState ballState =
                    ((BallFinishObservable) observable).getState();
            switch (ballState) {
                case RELEASE:
                    isVisible = false;
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * Listener for move the icon with the ball movement
     */
    private class BallMoveListener implements Observer {
        @Override
        public void update(Observable observable, Object data) {
            BallMoveObservable ballMoveObservable = (BallMoveObservable) observable;
            int ballPositionX = ballMoveObservable.getBallPosition();
            iconXPosition = ballPositionX - iconMargin;
        }
    }

    private class EnterValueAnimatorListener
            implements AnimatorValue.ValueUpdateListener {
        @Override
        public void onUpdate(AnimatorValue animatorValue, float v) {
            iconYPosition = (int) AnimatorValueUtils.getAnimatedValue(v,
                    enterAnimationStartValue,
                    middle - iconMargin);
        }
    }

    private class ExitValueAnimatorListener
            implements AnimatorValue.ValueUpdateListener {
        @Override
        public void onUpdate(AnimatorValue animatorValue, float v) {
            iconYPosition = (int) AnimatorValueUtils.getAnimatedValue(v,
                    middle - iconMargin,
                    middle - iconMargin + exitAnimationExitValue);
        }
    }
}
